﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using EasyClassWEBAPI.EntityClass;
using EasyClassWEBAPI.Models;
using EasyClassWEBAPI.Utils;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Nancy;
using System.Collections.Concurrent;

namespace EasyClassWEBAPI.Controllers
{
    [Route("Group")]
    [ApiController]
    public class StudyGroupController : ControllerBase
    {
        private EasyClassContext db;
        public StudyGroupController(EasyClassContext context)
        {
            this.db = context;
        }
        /// <summary>
        /// 创建学习小组 Post:group/add
        /// 需要在Header中加入Authorization传递当前创建用户的Token
        /// </summary>
        /// <param name="group"></param>
        /// <returns></returns>
        [HttpPost("Add")]
        public async Task<IActionResult> CreateStudyGroup(StudyGroup group)
        {
            try
            {
                //获取Token标识的用户
                string token = this.Request.Headers["Authorization"];
                User Founder = await db.Users.FirstOrDefaultAsync(o => o.Token == token);
                //如果用户不存在
                if (Founder == null) return NotFound("User didn't exist!");
                if (await db.StudyGroups.FirstOrDefaultAsync(o => o.StudyGroupName == group.StudyGroupName) != null)
                    return BadRequest("StudyGroup has exist!");
                group.User = Founder;//建立联系
                group.Members = TypeToString.ListToString(new List<string> { $"{Founder.UserAccount}" });
                db.StudyGroups.Add(group);
                

                //Founder.StudyGroups.Add(group);
                await db.SaveChangesAsync();
                //成功创建小组返回学习小组的ID，便于后续
                return Ok(group.StudyGroupID);
            }catch(Exception error)
            {
                return BadRequest($"Add StudyGroup {group.StudyGroupName} Failed.\n {error.Message}");
            }
        }
        /// <summary>
        /// 加入学习小组 PUT:group/join
        /// </summary>
        /// <param name="StudyGroupID"></param>
        /// <returns></returns>
        [HttpPut("Join")]
        public async Task<IActionResult> JoinStudyGroup(int StudyGroupID)
        {
            //获取Token标识的用户
            string token = this.Request.Headers["Authorization"];
            var user = await db.Users.Include("StudyGroups").FirstOrDefaultAsync(o => o.Token == token);
            //如果用户不存在
            if (user == null) return NotFound("User didn't exist!");

            var group = await db.StudyGroups.FirstOrDefaultAsync(o => o.StudyGroupID == StudyGroupID);
            //如果学习小组不存在
            if (group == null) return BadRequest("StudyGroupID error!");
            List<string> users = TypeToString.StringToList(group.Members);
            //如果此用户还未加入此学习小组
            if (!users.Contains(user.UserAccount))
            {
                users.Add(user.UserAccount);
                group.Members = TypeToString.ListToString(users);
                await db.SaveChangesAsync();
                return Ok("Join this group successfully!");
            }
            else
                return BadRequest("This user has already join this group");
        }
        /// <summary>
        /// 查询一个用户所有已经加入的学习小组 Get：group/querygroups
        /// </summary>
        /// <returns></returns>
        [HttpGet("QueryGroups")]
        public async Task<IActionResult> QueryGroupsAsync()
        {
            try
            {
                //获取Token标识的用户
                string token = this.Request.Headers["Authorization"];
                var user = await db.Users.FirstOrDefaultAsync(o => o.Token == token);
                if (user == null) return NotFound("User didn't exist!");
                var groupInfos = db.StudyGroups.Include(o => o.User).Include(o=>o.StudyResources).Include(o=>o.Posts)
                    .Where(o => o.Members.Contains(user.UserAccount));
                //去除不必要的信息
                groupInfos.AsParallel().ForAll(o =>
                {
                    o.User.Password = null;
                    o.User.Token = null;
                    o.User.StudyGroups = null;
                    o.User.Posts = null;
                    o.StudyResources = o.StudyResources.Where(o => o.Post == null).ToList();
                });
                return Ok(groupInfos);
            }
            catch(Exception error)
            {
                return BadRequest($"Search Failed! {error.Message}");
            }
        }
        /// <summary>
        /// 查询一个学习小组中所有的用户 Get:group/queryaccount
        /// </summary>
        /// <param name="StudyGroupID"></param>
        /// <returns></returns>
        [HttpGet("QueryAccount")]
        public async Task<IActionResult> QueryAccount(int StudyGroupID)
        {
            var group = await db.StudyGroups.FirstOrDefaultAsync(o => o.StudyGroupID == StudyGroupID);
            //如果学习小组不存在
            if (group == null) return BadRequest("StudyGroupID error!");
            List<string> Accounts = TypeToString.StringToList(group.Members);
            return Ok(Accounts);
        }
        /// <summary>
        /// 根据关键词查询群组 Get：group/SearhName
        /// SearchName：用户输入的群组信息 
        /// </summary>
        /// <param name="SearchName"></param>
        /// <returns></returns>
        [HttpGet("SearchByName")]
        public async Task<IActionResult> SearchByTitle(string SearchName)
        {
            try
            {
                if (SearchName == null)
                    return BadRequest("You should send Search string firstly!");
                //使用线程安全类ConcurrentBag避免线程数据丢失
                List<StudyGroup> resList = await db.StudyGroups.Include(o=>o.StudyResources).ToListAsync();
                ConcurrentBag<StudyGroup> res = new ConcurrentBag<StudyGroup>(resList);

                List<string> namesList = await db.StudyGroups.Select(o => o.StudyGroupName).ToListAsync();
                ConcurrentBag<string> names = new ConcurrentBag<string>(namesList);

                ConcurrentDictionary<string, double> similarity = new ConcurrentDictionary<string, double>();
                //使用编辑距离计算相似度
                //names.ForEach(o => similarity[o] = SimilarityComputation.DamerauLevenshteinMethod(SearchName, o));
                //res = res.OrderBy(o => similarity[o.StudyGroupName]).ToList();
                //使用LCS距离计算相似度
                //names.ForEach(o => similarity[o] = SimilarityComputation.LCSMethod(SearchName, o));
                Parallel.ForEach(names, o => similarity[o] = SimilarityComputation.LCSMethod(SearchName, o));
                res.OrderBy(o => similarity[o.StudyGroupName]);
                return Ok(res);
            }catch(Exception error)
            {
                return BadRequest($"Serch StudyGroup By Title Failed, Reson :{error.Message}");
            }
        }
        /// <summary>
        /// 查询一个小组里面的所有文件，包括帖子的附件 Get:Group/Files
        /// </summary>
        /// <param name="StudyGroupID"></param>
        /// <returns></returns>
        [HttpGet("Files")]
        public async Task<IActionResult> GetAllFiles(int StudyGroupID)
        {
            try
            {
                var group = await db.StudyGroups.FirstOrDefaultAsync(o => o.StudyGroupID == StudyGroupID);
                var files = db.StudyResources.Where(o => o.StudyGroup == o.StudyGroup);
                files.AsParallel().ForAll(o =>
                {
                    o.StudyGroup = null;
                });
                return Ok(files);
            }catch(Exception error)
            {
                return BadRequest(error.Message);
            }
        }

        /// <summary>
        /// 测试方法（后续删除）
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult test()
        {
            return Ok(db.Users.Include("StudyGroups").FirstOrDefault(o=>o.UserAccount=="lsq123").StudyGroups.Count());
        }
    }

}
